﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; using Montana.DAC;
using System.Data;

namespace Montana.Entidades
{
    public class Factura : Datos<Factura>, IDocumento
    {
        public string Letra { get; set; }
        public DateTime Fecha { get; set; }
        public int IDCliente { get; set; }
        public string Cliente { get; set; }
        public string Codigocliente { get; set; }
        public string Domicilioentrega { get; set; }
        public int IDLocalidad { get; set; }
        public string Localidad { get; set; }
        public string Numeroremito { get; set; }
        public decimal Subtotal { get; set; }
        public decimal Porcentajebonificacion { get; set; }
        public decimal Importebonificacion { get; set; }
        public decimal Porcentajeiva { get; set; }
        public decimal Importeiva { get; set; }
        public decimal Importetotal { get; set; }
        public decimal Importeentregado { get; set; }
        public string Efectivoescontable { get; set; }
        public decimal Saldoparcial { get; set; }
        public decimal Saldoanterior { get; set; }
        public decimal Saldoanterior2 { get; set; }

        public string Imprimirefectivo { get; set; }
        public string Imprimircheques { get; set; }
        public string Imprimirresagos { get; set; }
        public string Imprimirsaldos { get; set; }
        public string Imprimirdatoscontables { get; set; }

        public decimal Totalresagosproductos { get; set; }
        public decimal Saldofavorresagos { get; set; }
        public decimal Totalresagos { get; set; }
        public decimal Totalresagosentregados { get; set; }
        public decimal Saldonuevoresagos { get; set; }

        public decimal Saldocheques { get; set; }
        public double Saldoresagos { get; set; }

        public decimal Importecancelado { get; set; }

        public decimal Mermaporcentaje { get; set; }
        public decimal Mermakilos { get; set; }

        public string Tipo { get { return "FC"; } set { } }

        protected override string SQLBasico
        {
            get 
            {
                return @"select factura.*, c.nombre as cliente, c.codigo as codigocliente, l.nombre as localidad
                            from ((factura inner join cliente c on factura.idcliente=c.id) 
                                    left join localidad l on c.idlocalidad=l.id)";
            }
        }

        public string ObtenerUltimoNumero()
        {
            string sql = "select numerofactura from opciones where id=@id";

            return TraerValor(sql, 1).ToString();
        }

        public int Nueva(List<FacturaProducto> productos, List<Cheque> cheques, List<Resago> resagos, decimal nuevoSaldo, decimal nuevoSaldoKg)
        {
            Conectar();
            IniciarTransaccion();

            string sql = "";

            try
            {                
                sql = @"insert into factura (nombre, letra, fecha, idcliente, domicilioEntrega, 
                        idlocalidad, numeroremito, porcentajeiva, importeiva, 
                        importetotal, importeentregado, subtotal, porcentajebonificacion, importebonificacion, saldoparcial,
                        TotalResagosProductos, SaldoFavorResagos, TotalResagos, TotalResagosEntregados, SaldoNuevoResagos,
                        SaldoAnterior, EfectivoEsContable, ImporteCancelado, mermaporcentaje, Mermakilos, saldoAnterior2) 
                        values (@nombre, @letra, @fecha, @idcliente, @domicilioentrega, 
                        @idlocalidad, @numeroremito, @porcentajeiva, @importeiva, 
                        @importetotal, @importeentregado, @subtotal, @porcentajebonificacion, @importebonificacion, @saldoparcial,
                        @TotalResagosProductos, @SaldoFavorResagos, @TotalResagos, @TotalResagosEntregados, @SaldoNuevoResagos,
                        @SaldoAnterior, @EfectivoEsContable, @ImporteCancelado, @mermaporcentaje, @Mermakilos, @saldoAnterior2)";

                Ejecutar(sql, this);

                int idFactura = (int)TraerValor("SELECT @@IDENTITY");
                
                foreach (FacturaProducto prod in productos)
                {
                    prod.IDFactura = idFactura;
                    prod.Guardar();
                }

                decimal importeCheques = 0;
                foreach (Cheque che in cheques)
                {
                    che.IDFactura = idFactura;
                    che.IDCliente = this.IDCliente;
                    che.Guardar();

                    importeCheques += che.Importe;
                }

                decimal importeResagos = 0;
                foreach (Resago res in resagos)
                {
                    res.IDFactura = idFactura;
                    res.Guardar();

                    importeResagos += (res.Kilos * res.Preciokilo);
                }

                //guarda el recibo 
                if (this.Importeentregado != 0 || cheques.Count != 0 || resagos.Count != 0)
                {
                    Recibo rec = new Recibo();

                    rec.Fecha = DateTime.Parse(DateTime.Now.ToShortDateString());
                    rec.IDCliente = this.IDCliente;
                    rec.Importeefectivo = this.Importeentregado;
                    rec.Importecheques = importeCheques;
                    rec.Importeresagos = importeResagos;
                    
                    this.ID = idFactura;
                    rec.NuevoReciboFactura(cheques, resagos, this, null);
                }

                //sql = "update cliente set saldo=@nuevoSaldo, saldokg=@nuevoSaldoKg  where id=@id";
                //Ejecutar(sql, nuevoSaldo, nuevoSaldoKg, this.IDCliente);

                sql = "update opciones set numerofactura=@numeroFactura where id=@id";
                int numeroFactura = int.Parse(this.Nombre);
                Ejecutar(sql, String.Format("{0:00000000}", numeroFactura + 1), 1);

                TerminarTransaccion();

                return idFactura;
            }
            catch (Exception ex)
            {
                AbortarTransaccion();
                throw ex;
            }
        }

        public DataSet TraerReporteFactura(int idFactura)
        {
            string sql;
            DataSet ds;

            sql = "select * from factura where id=@id";
            ds = TraerDataSet(sql, idFactura);

            return ds;
        }

        public Factura BuscarPorNumero(string numeroFactura)
        {
            numeroFactura = String.Format("{0:00000000}", int.Parse(numeroFactura));

            List<Factura> facturas = TraerObjetos(SQLBasico + " where factura.nombre=@numeroFactura", numeroFactura);

            if (facturas.Count == 0)
                return null;
            else
                return facturas[0];
        }

        public void ReporteRemito(DataSet ds, int idFactura)
        {
            DataTable dt = TraerDataSet(SQLBasico + " where factura.id=" + idFactura).Tables[0];

            dt.TableName = "Factura";

            ds.Tables.Add(dt.Clone());
        }

        public void GuardarConfiguracionReporte(int idFactura, string mostrarEfectivo, string mostrarCheques, string mostrarResagos, string mostrarSaldos, string mostrarDatosContables, string saldoResagos)
        {
            string sql = @"update factura set imprimirEfectivo=@imprimirEfectivo, imprimirCheques=@imprimirCheques, 
                            imprimirResagos=@imprimirResagos, imprimirSaldos=@imprimirSaldos, 
                            imprimirDatosContables=@imprimirDatosContables, imprimirSaldoResagos=@imprimirSaldoResagos 
                            where id=@id";

            Ejecutar(sql, mostrarEfectivo, mostrarCheques, mostrarResagos, mostrarSaldos, mostrarDatosContables, saldoResagos, idFactura);
        }

        public List<Factura> BuscarPendientesBlanco(int idCliente)
        {
            return BuscarPendientes(idCliente, "S");
        }

        public List<Factura> BuscarPendientesNegro(int idCliente)
        {
            return BuscarPendientes(idCliente, "N");
        }

        private List<Factura> BuscarPendientes(int idCliente, string datoContable)
        {
            string sql = @"select factura.nombre, factura.EfectivoEsContable, factura.Importeentregado
                                , factura.letra, factura.fecha, c.nombre as cliente
                                , c.codigo as codigocliente, l.nombre as localidad, factura.porcentajebonificacion
                                , factura.importeiva, factura.id, factura.importecancelado
                                , (select sum(importetotal) from facturaproducto 
                                    where idfactura=factura.id and datocontable='" + datoContable + @"') as ImporteTotal
                                , (select sum(pesounitario * ccur(cantidad)) from facturaproducto
                                    where idfactura=factura.id and datocontable='" + datoContable + @"' and espreciomanoobra='S') as TotalResagosProductos
                                , (select sum(ccur(kilos)) from resago
                                    where idfactura=factura.id and escontable='" + datoContable + @"') as TotalResagosEntregados
                                , (select sum(kilos * precioKilo) from resago where idfactura=factura.id and escontable='" + datoContable + @"') as Saldoresagos
                                , (select sum(importe) from cheque where idfactura=factura.id and escontable='" + datoContable + @"') as Saldocheques
                           FROM ((factura inner join cliente c on factura.idcliente=c.id) 
                                    left join localidad l on c.idlocalidad=l.id)
                           WHERE factura.idcliente=@idcliente and factura.importetotal > factura.importecancelado
                           ORDER BY factura.id asc";

            return TraerObjetos(sql, idCliente);
        }

        public Factura BuscarPendienteBlancoPorID(int idFactura)
        {
            return BuscarPendientePorID(idFactura, "S");
        }

        public Factura BuscarPendienteNegroPorID(int idFactura)
        {
            return BuscarPendientePorID(idFactura, "N");
        }

        private Factura BuscarPendientePorID(int idFactura, string datoContable)
        {
            string sql = @"select factura.nombre, factura.idcliente, factura.EfectivoEsContable, factura.Importeentregado
                                , factura.letra, factura.fecha, c.nombre as cliente
                                , c.codigo as codigocliente, l.nombre as localidad, factura.porcentajebonificacion
                                , factura.importeiva, factura.id, factura.importecancelado
                                , (select sum(importetotal) from facturaproducto 
                                    where idfactura=factura.id and datocontable='" + datoContable + @"') as ImporteTotal
                                , (select sum(pesounitario * ccur(cantidad)) from facturaproducto
                                    where idfactura=factura.id and datocontable='" + datoContable + @"' and espreciomanoobra='S') as TotalResagosProductos
                                , (select sum(ccur(kilos)) from resago
                                    where idfactura=factura.id and escontable='" + datoContable + @"') as TotalResagosEntregados
                                , (select sum(kilos * precioKilo) from resago where idfactura=factura.id and escontable='" + datoContable + @"') as Saldoresagos
                                , (select sum(importe) from cheque where idfactura=factura.id and escontable='" + datoContable + @"') as Saldocheques
                           FROM ((factura inner join cliente c on factura.idcliente=c.id) 
                                    left join localidad l on c.idlocalidad=l.id)
                           WHERE factura.id=@idfactura and factura.importetotal > factura.importecancelado
                           ORDER BY factura.id asc";

            List<Factura> facturas = TraerObjetos(sql, idFactura);

            if (facturas.Count != 0)
                return facturas[0];
            else
                return null;
        }

        public void CancelarConSaldo(int idFactura, int idCliente, decimal importeCancelar)
        {
            IniciarTransaccion();

            string sql = @"update factura set importecancelado=importecancelado+@importe where id=@idFactura";
            Ejecutar(sql, importeCancelar, idFactura);

            sql = @"update cliente set saldo=saldo+@importe where idcliente=@idcliente";
            Ejecutar(sql, importeCancelar, idCliente);

            TerminarTransaccion();
        }

        public void CancelarConSaldo2(int idFactura, int idCliente, decimal importeCancelar)
        {
            IniciarTransaccion();

            string sql = @"update factura set importecancelado=importecancelado+@importe where id=@idFactura";
            Ejecutar(sql, importeCancelar, idFactura);

            sql = @"update cliente set saldo2=saldo2+@importe where idcliente=@idcliente";
            Ejecutar(sql, importeCancelar, idCliente);

            TerminarTransaccion();
        }
    }
}
